package bma.common.langutil.core;

import java.lang.reflect.Method;
import java.text.MessageFormat;

/**
 * 
 * @author guanzhong
 * @since 1.0 (imported from BMA.ESP Project)
 * 
 */
public class DirectInvoker implements java.io.Serializable {

	private static final long serialVersionUID = 3256728364068123192L;

	private Object invokeObject;

	private Method method;

	private Object[] arguments;

	public DirectInvoker() {
		super();
	}

	public Object[] getArguments() {
		return arguments;
	}

	public void setArguments(Object[] arguments) {
		this.arguments = arguments;
	}

	public Object getInvokeObject() {
		return invokeObject;
	}

	public void setInvokeObject(Object invokeObject) {
		this.invokeObject = invokeObject;
	}

	public Method getMethod() {
		return method;
	}

	public void setMethod(Method method) {
		this.method = method;
	}

	public Object invoke() throws Exception {
		return invoke(null);
	}

	public Object invoke(Object obj, Object... dynArguments) {
		Object[] vals = buildDynamicArguments(arguments, dynArguments);
		return invoke(invokeObject, method, vals);
	}

	public static boolean isUnknow(Object obj) {
		return obj == JavaInvoker.UNKNOW;
	}

	public static Object[] buildDynamicArguments(Object[] paramVals,
			Object[] dynArguments) {
		int c = paramVals == null ? 0 : paramVals.length;
		Object[] vals = new Object[c];
		int j = 0;
		for (int i = 0; i < c; i++) {
			if (isUnknow(paramVals[i])) {
				if (dynArguments != null && j < dynArguments.length) {
					vals[i] = dynArguments[j++];
				} else {
					vals[i] = null;
				}
			} else {
				vals[i] = paramVals[i];
			}
		}
		return vals;
	}

	public static Object invoke(Object thisObject, Method method, Object[] vals) {
		try {
			return method.invoke(thisObject, vals);
		} catch (java.lang.reflect.InvocationTargetException e) {
			Throwable t = e.getTargetException();
			throw ExceptionUtil.throwRuntime(t);			
		} catch (Exception ee) {
			throw ExceptionUtil.throwRuntime(ee);
		}
	}

	public Class getThisClass() {
		if (invokeObject != null)
			return invokeObject.getClass();
		if (method != null)
			return method.getDeclaringClass();
		return null;
	}

	public DirectInvoker create(Object thisObject, Method method,
			Object[] params) {
		this.invokeObject = thisObject;
		this.method = method;
		this.arguments = params;
		return this;
	}

	public void clear() {
		this.invokeObject = null;
		this.method = null;
		this.arguments = null;
	}

	public String toShortString() {
		String cls = "null";
		Class c = getThisClass();
		if (c != null)
			cls = c.getName();
		return cls + "." + (method == null ? "[null]" : method.getName())
				+ "()";

	}

	@Override
	public String toString() {
		return MessageFormat.format("Invoker[{0},{1},{2}]", invokeObject,
				method, arguments);
	}

}